home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / r_warp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-18  |  12.5 KB  |  637 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_warp.c -- sky and water polygons
  21.  
  22. #include "r_local.h"
  23.  
  24. extern    model_t    *loadmodel;
  25.  
  26. char    skyname[MAX_QPATH];
  27. float    skyrotate;
  28. vec3_t    skyaxis;
  29. image_t    *sky_images[6];
  30.  
  31. msurface_t    *warpface;
  32.  
  33. #define    SUBDIVIDE_SIZE    64
  34. //#define    SUBDIVIDE_SIZE    1024
  35.  
  36. void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
  37. {
  38.     int        i, j;
  39.     float    *v;
  40.  
  41.     mins[0] = mins[1] = mins[2] = 9999;
  42.     maxs[0] = maxs[1] = maxs[2] = -9999;
  43.     v = verts;
  44.     for (i=0 ; i<numverts ; i++)
  45.         for (j=0 ; j<3 ; j++, v++)
  46.         {
  47.             if (*v < mins[j])
  48.                 mins[j] = *v;
  49.             if (*v > maxs[j])
  50.                 maxs[j] = *v;
  51.         }
  52. }
  53.  
  54. void SubdividePolygon (int numverts, float *verts)
  55. {
  56.     int        i, j, k;
  57.     vec3_t    mins, maxs;
  58.     float    m;
  59.     float    *v;
  60.     vec3_t    front[64], back[64];
  61.     int        f, b;
  62.     float    dist[64];
  63.     float    frac;
  64.     glpoly_t    *poly;
  65.     float    s, t;
  66.     vec3_t    total;
  67.     float    total_s, total_t;
  68.  
  69.     if (numverts > 60)
  70.         Com_Error (ERR_DROP, "numverts = %i", numverts);
  71.  
  72.     BoundPoly (numverts, verts, mins, maxs);
  73.  
  74.     for (i=0 ; i<3 ; i++)
  75.     {
  76.         m = (mins[i] + maxs[i]) * 0.5;
  77.         m = SUBDIVIDE_SIZE * floor (m/SUBDIVIDE_SIZE + 0.5);
  78.         if (maxs[i] - m < 8)
  79.             continue;
  80.         if (m - mins[i] < 8)
  81.             continue;
  82.  
  83.         // cut it
  84.         v = verts + i;
  85.         for (j=0 ; j<numverts ; j++, v+= 3)
  86.             dist[j] = *v - m;
  87.  
  88.         // wrap cases
  89.         dist[j] = dist[0];
  90.         v-=i;
  91.         VectorCopy (verts, v);
  92.  
  93.         f = b = 0;
  94.         v = verts;
  95.         for (j=0 ; j<numverts ; j++, v+= 3)
  96.         {
  97.             if (dist[j] >= 0)
  98.             {
  99.                 VectorCopy (v, front[f]);
  100.                 f++;
  101.             }
  102.             if (dist[j] <= 0)
  103.             {
  104.                 VectorCopy (v, back[b]);
  105.                 b++;
  106.             }
  107.             if (dist[j] == 0 || dist[j+1] == 0)
  108.                 continue;
  109.             if ( (dist[j] > 0) != (dist[j+1] > 0) )
  110.             {
  111.                 // clip point
  112.                 frac = dist[j] / (dist[j] - dist[j+1]);
  113.                 for (k=0 ; k<3 ; k++)
  114.                     front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
  115.                 f++;
  116.                 b++;
  117.             }
  118.         }
  119.  
  120.         SubdividePolygon (f, front[0]);
  121.         SubdividePolygon (b, back[0]);
  122.         return;
  123.     }
  124.  
  125.     // add a point in the center to help keep warp valid
  126.     poly = Hunk_Alloc (sizeof(glpoly_t) + ((numverts-4)+2) * VERTEXSIZE*sizeof(float));
  127.     poly->next = warpface->polys;
  128.     warpface->polys = poly;
  129.     poly->numverts = numverts+2;
  130.     VectorClear (total);
  131.     total_s = 0;
  132.     total_t = 0;
  133.     for (i=0 ; i<numverts ; i++, verts+= 3)
  134.     {
  135.         VectorCopy (verts, poly->verts[i+1]);
  136.         s = DotProduct (verts, warpface->texinfo->vecs[0]);
  137.         t = DotProduct (verts, warpface->texinfo->vecs[1]);
  138.  
  139.         total_s += s;
  140.         total_t += t;
  141.         VectorAdd (total, verts, total);
  142.  
  143.         poly->verts[i+1][3] = s;
  144.         poly->verts[i+1][4] = t;
  145.     }
  146.  
  147.     VectorScale (total, (1.0/numverts), poly->verts[0]);
  148.     poly->verts[0][3] = total_s/numverts;
  149.     poly->verts[0][4] = total_t/numverts;
  150.  
  151.     // copy first vertex to last
  152.     memcpy (poly->verts[i+1], poly->verts[1], sizeof(poly->verts[0]));
  153. }
  154.  
  155. /*
  156. ================
  157. GL_SubdivideSurface
  158.  
  159. Breaks a polygon up along axial 64 unit
  160. boundaries so that turbulent and sky warps
  161. can be done reasonably.
  162. ================
  163. */
  164. void GL_SubdivideSurface (msurface_t *fa)
  165. {
  166.     vec3_t        verts[64];
  167.     int            numverts;
  168.     int            i;
  169.     int            lindex;
  170.     float        *vec;
  171.  
  172.     warpface = fa;
  173.  
  174.     //
  175.     // convert edges back to a normal polygon
  176.     //
  177.     numverts = 0;
  178.     for (i=0 ; i<fa->numedges ; i++)
  179.     {
  180.         lindex = loadmodel->surfedges[fa->firstedge + i];
  181.  
  182.         if (lindex > 0)
  183.             vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
  184.         else
  185.             vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
  186.         VectorCopy (vec, verts[numverts]);
  187.         numverts++;
  188.     }
  189.  
  190.     SubdividePolygon (numverts, verts[0]);
  191. }
  192.  
  193. //=========================================================
  194.  
  195.  
  196.  
  197. // speed up sin calculations - Ed
  198. float    r_turbsin[] =
  199. {
  200.     #include "warpsin.h"
  201. };
  202. #define TURBSCALE (256.0 / (2 * M_PI))
  203.  
  204. /*
  205. =============
  206. EmitWaterPolys
  207.  
  208. Does a water warp on the pre-fragmented glpoly_t chain
  209. =============
  210. */
  211. void EmitWaterPolys (msurface_t *fa)
  212. {
  213.     glpoly_t    *p;
  214.     float        *v;
  215.     int            i;
  216.     float        s, t, os, ot;
  217.     float        scroll;
  218.     float        rdt = r_newrefdef.time;
  219.  
  220.     if (fa->texinfo->flags & SURF_FLOWING)
  221.         scroll = -64 * ( (r_newrefdef.time*0.5) - (int)(r_newrefdef.time*0.5) );
  222.     else
  223.         scroll = 0;
  224.     for (p=fa->polys ; p ; p=p->next)
  225.     {
  226.         qglBegin (GL_TRIANGLE_FAN);
  227.         for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
  228.         {
  229.             os = v[3];
  230.             ot = v[4];
  231.  
  232. #if !id386
  233.             s = os + r_turbsin[(int)((ot*0.125+r_newrefdef.time) * TURBSCALE) & 255];
  234. #else
  235.             s = os + r_turbsin[Q_ftol( ((ot*0.125+rdt) * TURBSCALE) ) & 255];
  236. #endif
  237.             s += scroll;
  238.             s *= (1.0/64);
  239.  
  240. #if !id386
  241.             t = ot + r_turbsin[(int)((os*0.125+rdt) * TURBSCALE) & 255];
  242. #else
  243.             t = ot + r_turbsin[Q_ftol( ((os*0.125+rdt) * TURBSCALE) ) & 255];
  244. #endif
  245.             t *= (1.0/64);
  246.  
  247.             qglTexCoord2f (s, t);
  248.             qglVertex3fv (v);
  249.         }
  250.         qglEnd ();
  251.     }
  252. }
  253.  
  254.  
  255. //===================================================================
  256.  
  257.  
  258. vec3_t    skyclip[6] = {
  259.     {1,1,0},
  260.     {1,-1,0},
  261.     {0,-1,1},
  262.     {0,1,1},
  263.     {1,0,1},
  264.     {-1,0,1} 
  265. };
  266.  
  267. // 1 = s, 2 = t, 3 = 2048
  268. int    st_to_vec[6][3] =
  269. {
  270.     {3,-1,2},
  271.     {-3,1,2},
  272.  
  273.     {1,3,2},
  274.     {-1,-3,2},
  275.  
  276.     {-2,-1,3},        // 0 degrees yaw, look straight up
  277.     {2,-1,-3}        // look straight down
  278.  
  279. //    {-1,2,3},
  280. //    {1,2,-3}
  281. };
  282.  
  283. // s = [0]/[2], t = [1]/[2]
  284. int    vec_to_st[6][3] =
  285. {
  286.     {-2,3,1},
  287.     {2,3,-1},
  288.  
  289.     {1,3,2},
  290.     {-1,3,-2},
  291.  
  292.     {-2,-1,3},
  293.     {-2,1,-3}
  294.  
  295. //    {-1,2,3},
  296. //    {1,2,-3}
  297. };
  298.  
  299. float    skymins[2][6], skymaxs[2][6];
  300. float    sky_min, sky_max;
  301.  
  302. void DrawSkyPolygon (int nump, vec3_t vecs)
  303. {
  304.     int        i,j;
  305.     vec3_t    v, av;
  306.     float    s, t, dv;
  307.     int        axis;
  308.     float    *vp;
  309.  
  310.     // decide which face it maps to
  311.     VectorCopy (vec3_origin, v);
  312.     for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
  313.     {
  314.         VectorAdd (vp, v, v);
  315.     }
  316.     av[0] = fabs(v[0]);
  317.     av[1] = fabs(v[1]);
  318.     av[2] = fabs(v[2]);
  319.     if (av[0] > av[1] && av[0] > av[2])
  320.     {
  321.         if (v[0] < 0)
  322.             axis = 1;
  323.         else
  324.             axis = 0;
  325.     }
  326.     else if (av[1] > av[2] && av[1] > av[0])
  327.     {
  328.         if (v[1] < 0)
  329.             axis = 3;
  330.         else
  331.             axis = 2;
  332.     }
  333.     else
  334.     {
  335.         if (v[2] < 0)
  336.             axis = 5;
  337.         else
  338.             axis = 4;
  339.     }
  340.  
  341.     // project new texture coords
  342.     for (i=0 ; i<nump ; i++, vecs+=3)
  343.     {
  344.         j = vec_to_st[axis][2];
  345.         if (j > 0)
  346.             dv = vecs[j - 1];
  347.         else
  348.             dv = -vecs[-j - 1];
  349.         if (dv < 0.001)
  350.             continue;    // don't divide by zero
  351.         j = vec_to_st[axis][0];
  352.         if (j < 0)
  353.             s = -vecs[-j -1] / dv;
  354.         else
  355.             s = vecs[j-1] / dv;
  356.         j = vec_to_st[axis][1];
  357.         if (j < 0)
  358.             t = -vecs[-j -1] / dv;
  359.         else
  360.             t = vecs[j-1] / dv;
  361.  
  362.         if (s < skymins[0][axis])
  363.             skymins[0][axis] = s;
  364.         if (t < skymins[1][axis])
  365.             skymins[1][axis] = t;
  366.         if (s > skymaxs[0][axis])
  367.             skymaxs[0][axis] = s;
  368.         if (t > skymaxs[1][axis])
  369.             skymaxs[1][axis] = t;
  370.     }
  371. }
  372.  
  373. #define    ON_EPSILON        0.1            // point on plane side epsilon
  374. #define    MAX_CLIP_VERTS    64
  375. void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
  376. {
  377.     float    *norm;
  378.     float    *v;
  379.     qboolean    front, back;
  380.     float    d, e;
  381.     float    dists[MAX_CLIP_VERTS];
  382.     int        sides[MAX_CLIP_VERTS];
  383.     vec3_t    newv[2][MAX_CLIP_VERTS];
  384.     int        newc[2];
  385.     int        i, j;
  386.  
  387.     if (nump > MAX_CLIP_VERTS-2)
  388.         Com_Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
  389.     if (stage == 6)
  390.     {    // fully clipped, so draw it
  391.         DrawSkyPolygon (nump, vecs);
  392.         return;
  393.     }
  394.  
  395.     front = back = false;
  396.     norm = skyclip[stage];
  397.     for (i=0, v = vecs ; i<nump ; i++, v+=3)
  398.     {
  399.         d = DotProduct (v, norm);
  400.         if (d > ON_EPSILON)
  401.         {
  402.             front = true;
  403.             sides[i] = SIDE_FRONT;
  404.         }
  405.         else if (d < -ON_EPSILON)
  406.         {
  407.             back = true;
  408.             sides[i] = SIDE_BACK;
  409.         }
  410.         else
  411.             sides[i] = SIDE_ON;
  412.         dists[i] = d;
  413.     }
  414.  
  415.     if (!front || !back)
  416.     {    // not clipped
  417.         ClipSkyPolygon (nump, vecs, stage+1);
  418.         return;
  419.     }
  420.  
  421.     // clip it
  422.     sides[i] = sides[0];
  423.     dists[i] = dists[0];
  424.     VectorCopy (vecs, (vecs+(i*3)) );
  425.     newc[0] = newc[1] = 0;
  426.  
  427.     for (i=0, v = vecs ; i<nump ; i++, v+=3)
  428.     {
  429.         switch (sides[i])
  430.         {
  431.         case SIDE_FRONT:
  432.             VectorCopy (v, newv[0][newc[0]]);
  433.             newc[0]++;
  434.             break;
  435.         case SIDE_BACK:
  436.             VectorCopy (v, newv[1][newc[1]]);
  437.             newc[1]++;
  438.             break;
  439.         case SIDE_ON:
  440.             VectorCopy (v, newv[0][newc[0]]);
  441.             newc[0]++;
  442.             VectorCopy (v, newv[1][newc[1]]);
  443.             newc[1]++;
  444.             break;
  445.         }
  446.  
  447.         if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  448.             continue;
  449.  
  450.         d = dists[i] / (dists[i] - dists[i+1]);
  451.         for (j=0 ; j<3 ; j++)
  452.         {
  453.             e = v[j] + d*(v[j+3] - v[j]);
  454.             newv[0][newc[0]][j] = e;
  455.             newv[1][newc[1]][j] = e;
  456.         }
  457.         newc[0]++;
  458.         newc[1]++;
  459.     }
  460.  
  461.     // continue
  462.     ClipSkyPolygon (newc[0], newv[0][0], stage+1);
  463.     ClipSkyPolygon (newc[1], newv[1][0], stage+1);
  464. }
  465.  
  466. /*
  467. =================
  468. R_AddSkySurface
  469. =================
  470. */
  471. void R_AddSkySurface (msurface_t *fa)
  472. {
  473.     int            i;
  474.     vec3_t        verts[MAX_CLIP_VERTS];
  475.     glpoly_t    *p;
  476.  
  477.     // calculate vertex values for sky box
  478.     for (p=fa->polys ; p ; p=p->next)
  479.     {
  480.         for (i=0 ; i<p->numverts ; i++)
  481.         {
  482.             VectorSubtract (p->verts[i], r_origin, verts[i]);
  483.         }
  484.         ClipSkyPolygon (p->numverts, verts[0], 0);
  485.     }
  486. }
  487.  
  488.  
  489. /*
  490. ==============
  491. R_ClearSkyBox
  492. ==============
  493. */
  494. void R_ClearSkyBox (void)
  495. {
  496.     int        i;
  497.  
  498.     for (i=0 ; i<6 ; i++)
  499.     {
  500.         skymins[0][i] = skymins[1][i] = 9999;
  501.         skymaxs[0][i] = skymaxs[1][i] = -9999;
  502.     }
  503. }
  504.  
  505.  
  506. void MakeSkyVec (float s, float t, int axis)
  507. {
  508.     vec3_t        v, b;
  509.     int            j, k;
  510.  
  511.     b[0] = s*3300; //JKD - 9/24/02 this was at 2300 across the board, 3300 fixes 
  512.     b[1] = t*3300; // problems with skyboxes being too small for the large 
  513.     b[2] = 3300;   // outdoor, city levels.
  514.  
  515.     for (j=0 ; j<3 ; j++)
  516.     {
  517.         k = st_to_vec[axis][j];
  518.         if (k < 0)
  519.             v[j] = -b[-k - 1];
  520.         else
  521.             v[j] = b[k - 1];
  522.     }
  523.  
  524.     // avoid bilerp seam
  525.     s = (s+1)*0.5;
  526.     t = (t+1)*0.5;
  527.  
  528.     if (s < sky_min)
  529.         s = sky_min;
  530.     else if (s > sky_max)
  531.         s = sky_max;
  532.     if (t < sky_min)
  533.         t = sky_min;
  534.     else if (t > sky_max)
  535.         t = sky_max;
  536.  
  537.     t = 1.0 - t;
  538.     qglTexCoord2f (s, t);
  539.     qglVertex3fv (v);
  540. }
  541.  
  542. /*
  543. ==============
  544. R_DrawSkyBox
  545. ==============
  546. */
  547. int    skytexorder[6] = {0,2,1,3,4,5};
  548. void R_DrawSkyBox (void)
  549. {
  550.     int        i;
  551.  
  552.     if (skyrotate)
  553.     {    // check for no sky at all
  554.         for (i=0 ; i<6 ; i++)
  555.             if (skymins[0][i] < skymaxs[0][i]
  556.             && skymins[1][i] < skymaxs[1][i])
  557.                 break;
  558.         if (i == 6)
  559.             return;        // nothing visible
  560.     }
  561.  
  562.     qglPushMatrix ();
  563.     qglTranslatef (r_origin[0], r_origin[1], r_origin[2]);
  564.     qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);
  565.  
  566.     for (i=0 ; i<6 ; i++)
  567.     {
  568.         if (skyrotate)
  569.         {    // hack, forces full sky to draw when rotating
  570.             skymins[0][i] = -1;
  571.             skymins[1][i] = -1;
  572.             skymaxs[0][i] = 1;
  573.             skymaxs[1][i] = 1;
  574.         }
  575.  
  576.         if (skymins[0][i] >= skymaxs[0][i]
  577.         || skymins[1][i] >= skymaxs[1][i])
  578.             continue;
  579.  
  580.         GL_Bind (sky_images[skytexorder[i]]->texnum);
  581.  
  582.         qglBegin (GL_QUADS);
  583.         MakeSkyVec (skymins[0][i], skymins[1][i], i);
  584.         MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
  585.         MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
  586.         MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
  587.         qglEnd ();
  588.     }
  589.     qglPopMatrix ();
  590. }
  591.  
  592.  
  593. /*
  594. ============
  595. R_SetSky
  596. ============
  597. */
  598. // 3dstudio environment map names
  599. char    *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
  600. void R_SetSky (char *name, float rotate, vec3_t axis)
  601. {
  602.     int        i;
  603.     char    pathname[MAX_QPATH];
  604.  
  605.     strncpy (skyname, name, sizeof(skyname)-1);
  606.     skyrotate = rotate;
  607.     VectorCopy (axis, skyaxis);
  608.  
  609.     for (i=0 ; i<6 ; i++)
  610.     {
  611.         // chop down rotating skies for less memory
  612.         if (gl_skymip->value || skyrotate)
  613.             gl_picmip->value++;
  614.  
  615.         if ( qglColorTableEXT && gl_ext_palettedtexture->value )
  616.             Com_sprintf (pathname, sizeof(pathname), "env/%s%s.pcx", skyname, suf[i]);
  617.         else
  618.             Com_sprintf (pathname, sizeof(pathname), "env/%s%s.tga", skyname, suf[i]);
  619.  
  620.         sky_images[i] = GL_FindImage (pathname, it_sky);
  621.         if (!sky_images[i])
  622.             sky_images[i] = r_notexture;
  623.  
  624.         if (gl_skymip->value || skyrotate)
  625.         {    // take less memory
  626.             gl_picmip->value--;
  627.             sky_min = 1.0/256;
  628.             sky_max = 255.0/256;
  629.         }
  630.         else    
  631.         {
  632.             sky_min = 1.0/512;
  633.             sky_max = 511.0/512;
  634.         }
  635.     }
  636. }
  637.